/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.aliang.jp.jp;

import java.awt.Cursor;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

/**
 * 修改状态
 * @author liuruile
 */
public class ModifyState extends State {

    private Point pressPoint; // 记录鼠标按下时点，用来计算拖动选择区时移动的距离

    /**
     * 保证起始点和终止点的位置正确，起点始终是“左上（也就是NW）”
     * 终点始终是“右下（也就是SE）”
     */
    private void ensureStartEndRight() {
        if (start.x > end.x) {
            int x = start.x;
            start.x = end.x;
            end.x = x;
        }
        if (start.y > end.y) {
            int y = start.y;
            start.y = end.y;
            end.y = y;
        }
    }

    // 表示修改状态下10个子状态，需要向哪个方向调整，前面8个表示8个调整方向，
    // MOVE表示对选择区进行移动，NONE表示什么也不做
    private enum MState {

        NW, N, NE, E, SE, S, SW, W, MOVE, NONE
    };
    // 默认的当前状态为NONE
    private MState now = MState.NONE;

    @Override
    /**
     * 记录鼠标按下时点，用来计算拖动选择区时移动的距离
     */
    public void mousePressed(MouseEvent e) {
        pressPoint = e.getPoint();
    }

    @Override
    /**
     * 左键双击－－＞ 保存抓取区域，本次抓屏操作结束
     * 右键双击－－＞ 取消抓取，本次抓屏操作结束
     * 右键单击－－＞ 修改状态 －－跳转到－－＞ 选择状态，并取消当前选择区，由用户重新选择
     */
    public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
            // 左键双击
            if (e.getButton() == MouseEvent.BUTTON1) {

                Rectangle rct = getSelectedRect();

                SystemTrayTool.outputImage2SavePlace(parent.im, rct);

                start = null;
                end = null;
                parent.dispose();
            } else {
                // 右键双击
                start = null;
                end = null;
                parent.dispose();
            }
        } else if (e.getClickCount() == 1 && e.getButton() == MouseEvent.BUTTON3) {
            end = start;
            State.changeState(this, State.getSelectState());
            parent.rectPanel.repaint();
        }
    }

    @Override
    /**
     * 鼠标释放时检查一下起点和终点的正确性
     */
    public void mouseReleased(MouseEvent e) {
        ensureStartEndRight();
    }

    @Override
    /**
     * 根据当前具体的是在哪个方向的修改来调整选择区的起点和终点的位置
     */
    public void mouseDragged(MouseEvent e) {
        boolean bRepaint = true;
        Point p = e.getPoint();
        int moveX = p.x - pressPoint.x;
        int moveY = p.y - pressPoint.y;
        pressPoint = p;
        switch (now) {
            case NW:
                movePoint(start,moveX, moveY);
                break;
            case N:
                movePoint(start, 0, moveY);
                break;
            case NE:
                movePoint(start, 0, moveY);
                movePoint(end, moveX, 0);
                break;
            case E:
                movePoint(end, moveX, 0);
                break;
            case SE:
                movePoint(end, moveX, moveY);
                break;
            case S:
                movePoint(end, 0, moveY);
                break;
            case SW:
                movePoint(start, moveX, 0);
                movePoint(end, 0, moveY);
                break;
            case W:
                movePoint(start,moveX, 0);
                break;
            case MOVE:
                movePoint(start, moveX, moveY);
                movePoint(end, moveX, moveY);
                break;
            default:
                bRepaint = false;
                break;
        }
        if (bRepaint) {
            parent.rectPanel.repaint();
        }

    }

    @Override
    /**
     * 鼠标移动到不同的位置时，根据当前的位置的含义设置鼠标的形状，
     * 并设置修改状态的具体子状态，明确是在哪个方向上的调整
     */
    public void mouseMoved(MouseEvent e) {
        now = meaningOfPoint(e.getPoint());
        switch (now) {
            case NW:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
                break;
            case N:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
                break;
            case NE:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
                break;
            case E:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
                break;
            case SE:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
                break;
            case S:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
                break;
            case SW:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
                break;
            case W:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
                break;
            case MOVE:
                parent.topFrame.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                break;
            default:
                parent.topFrame.setCursor(Cursor.getDefaultCursor());
                now = MState.NONE;
                break;
        }
    }

    /**
     * 明确传入点在修改状态下的具体的含义
     * @param point
     * @return 修改状态下的具体子状态
     */
    private MState meaningOfPoint(Point point) {
        Rectangle[] corners = getCornerRects();
        int index = -1;
        for (int i = 0; i < corners.length; i++) {
            if (corners[i].contains(point)) {
                index = i;
                break;
            }
        }
        if (index < 0) {
            if (getSelectedRect().contains(point)) {
                index = corners.length;
            } else {
                index = corners.length + 1;
            }
        }

        return MState.values()[index];
    }

    /**
     * 将传入的点的位置进行移动
     * @param point
     * @param moveX X方向移动的距离
     * @param moveY Y方向移动的距离
     */
    private void movePoint(Point point, int moveX, int moveY) {
        point.x = point.x + moveX;
        point.y = point.y + moveY;
    }
}
